#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Copyright (C) 2009 Daniele Favara.
# Written by Daniele Favara <daniele@zeroisp.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


import sys, os, smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate, formataddr, make_msgid
from email import Encoders



class Mailer(object):
    def __init__(self, server,user,password,
                 mail_from,mail_to,mail_subject,mail_body,
                 smtp_port=587,smtp_tls=True,smtp_debuglevel=0,mail_from_name=None):

        #SMTP
        self._server = server
        self._user = user
        self._password = password
        self._debuglevel = smtp_debuglevel
        self._port = smtp_port
        self._tls = smtp_tls

        #MAIL
        self._mail_from = mail_from
        self._mail_from_name = mail_from_name
        self._mail_to = mail_to # list
        self._mail_subject = mail_subject
        self._mail_body = mail_body
        self._smtp = smtplib.SMTP()
        self._msg = MIMEMultipart()

    def _get_debuglevel(self):
        return self._debuglevel

    debuglevel = property(_get_debuglevel)

    def _get_server(self):
        return self._server

    server = property(_get_server)

    def _get_password(self):
        return self._password

    password = property(_get_password)

    def _get_user(self):
        return self._user

    user = property(_get_user)

    def _get_tls(self):
        return self._tls

    tls = property(_get_tls)

    def _get_smtp(self):
        return self._smtp

    smtp = property(_get_smtp)


    def _get_mail_from(self):
        return self._mail_from

    mail_from = property(_get_mail_from)

    def _get_mail_from_name(self):
        return self._mail_from_name

    mail_from_name = property(_get_mail_from_name)

    def _get_mail_to(self):
        return COMMASPACE.join(self._mail_to)

    mail_to = property(_get_mail_to)

    def _get_mail_subject(self):
        return self._mail_subject

    mail_subject = property(_get_mail_subject)

    def _get_mail_body(self):
        return self._mail_body

    mail_body = property(_get_mail_body)

    def _get_mail_addr(self):
        if self.mail_from_name:
            self._mail_addr = formataddr((self.mail_from_name, self.mail_from))
        else:
            self._mail_addr = self.mail_from
        return self._mail_addr

    mail_addr = property(_get_mail_addr)

    def _get_msg(self):
        self._msg['From'] = self.mail_addr
        self._msg['To'] = self.mail_to
        self._msg['Date'] = formatdate()
        self._msg['Message-ID'] = make_msgid('tgext.zeroisp')
        self._msg['X-Zeroisp-Name'] = 'Tgext Zeroisp Mailer'
        self._msg['X-Zeroisp-Loop'] = 'hello'
        self._msg['Subject'] = self.mail_subject
        #self._msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
        # Fa in modo che il messaggio termini con un fine riga
        #self._msg.epilogue = ''
        self._msg.attach( MIMEText(self.mail_body) )
        return self._msg

    msg = property(_get_msg)

    def connected(self):
        """Return the current SMTP connection status."""

        return getattr(self.smtp, 'sock', None) is not None

    connected = property(connected)

    def connect(self):
        self.smtp.debuglevel = self.debuglevel

        self.smtp.connect(self.server)

        # try to do tls
        self.smtp.ehlo()
        #if self.smtp.has_extn('starttls'):
        if True:
            self.smtp.starttls()
            self.smtp.ehlo()
            self._tls = True

    def disconnect(self):
        """Disconnect from the SMTP server if connected."""

        if self.connected:
            self.smtp.quit()

    def login(self):
        """
        (235, 'Authentication successful')
        """
        try:
            return self.smtp.login(self.user, self.password)

        except smtplib.SMTPAuthenticationError, e:
            return (e.smtp_code, e.smtp_error)

    def send(self):
        self.connect()
        self.login()
        self.smtp.sendmail(self.mail_addr, self.mail_to, self.msg.as_string())

def main():
    import cgi
    import cgitb; cgitb.enable()  # for troubleshooting

    print "Content-type: text/html"
    print

    print """
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>

    <head>
        <title>Mailer CGI Script</title>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <style type="text/css">
            .error {color: red}
        </style>
    </head>

    <body>

      <h3> Mailer CGI Script </h3>
    """



    form = cgi.FieldStorage()

    validate = ['smtp.server',
                'smtp.user',
                'smtp.password',
                'mail.subject',
                'mail.body',
                'mail.from',
                'mail.to']


    has_post = False

    error = '<span class="error">Please insert a value</span>'


    values = {}
    for field in validate:
        values[field] = ''
        if form.has_key(field):
            has_post = True

    for field in validate:
        if has_post:
            values["%s.error" %(field)] = error
        else:
            values["%s.error" %(field)] = ''



    for field in form.keys():
        field_error = "%s.error" %(field)
        if form.has_key(field):
            if type(form[field]) ==  type([]):
                value = form.getlist(field)
            else:
                value = form[field].value

            values[field] = value

            if value:
                values[field_error] = ''

    sendme = True

    for field in validate:
        field_error = "%s.error" %(field)
        if values[field_error]:
            sendme = False
            break

    if has_post and sendme:
        mailer = Mailer(values['smtp.server'],
                        values['smtp.user'],
                        values['smtp.password'],
                        values['mail.from'],
                        [values['mail.to']],
                        values['mail.subject'],
                        values['mail.body']
                        )
        mailer.send()

        print "<pre>Mail Sent"

        print mailer.msg.as_string()
        print "TLS", mailer.smtp.has_extn('starttls')
        print "</pre>"

    else:
        print """

            <form method="post" action="mailer.cgi">
                <h4>SMTP SERVER</h4>
                <table>
                    <tr>
                        <th>server: </th>
                        <td><input type="text" name="smtp.server" value="%(smtp.server)s" size="30"/><span>%(smtp.server.error)s</span></td>
                    </tr>
                    <tr>
                        <th>user: </th>
                        <td><input type="text" name="smtp.user" value="%(smtp.user)s" size="30"/><span>%(smtp.user.error)s</span></td>
                    </tr>
                    <tr>
                        <th>password: </th>
                        <td><input type="password" name="smtp.password" value="%(smtp.password)s" size="30"/><span>%(smtp.password.error)s</span></td>
                    </tr>
                </table>
                <h4>MAIL</h4>
                <table>
                    <tr>
                        <th>from: </th>
                        <td><input type="text" name="mail.from" value="%(mail.from)s" size="30"/><span>%(mail.from.error)s</span></td>
                    </tr>
                    <tr>
                        <th>to: </th>
                        <td><input type="text" name="mail.to" value="%(mail.to)s" size="30"/><span>%(mail.to.error)s</span></td>
                    </tr>
                    <tr>
                        <th>subject: </th>
                        <td><input type="text" name="mail.subject" value="%(mail.subject)s" size="30"/><span>%(mail.subject.error)s</span></td>
                    </tr>
                    <tr>
                        <th>body: </th>
                        <td>
                            <p>%(mail.body.error)s</p>
                            <textarea name="mail.body" rows="10" cols="80">%(mail.body)s</textarea>
                        </td>
                    </tr>
                </table>
                <input name="action" value="Send" class="button" type="submit" />
            </form>
        """%(values)
    print """
        </body>
        </html>
    """

if __name__ == '__main__':
    main()
